/*
 * Copyright 2006 Berry Crawford
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.judo.generate.java;

import java.util.*;

import org.judo.generate.CodeGenerator;
import org.judo.generate.GenerationException;

public class ClassGenerator implements CodeGenerator
{
	protected String className;
	protected String packageName;
	protected String superClass;
	
	protected ArrayList fields = new ArrayList();
	protected ArrayList methods = new ArrayList();
	protected ArrayList interfaces = new ArrayList();
	protected ArrayList imports = new ArrayList();
	protected ArrayList props = new ArrayList();
	protected ArrayList<String> annotations = new ArrayList<String>();

	public void addAnnototation(String annotationCode)
	{
		annotations.add(annotationCode);
	}
	
	public String generate()
		throws GenerationException
	{
		String classCode = "";
		
		if (packageName != null)
			classCode += "package "+packageName+";\n\n";
		
		for (int i=0;i<imports.size();i++)
		{
			classCode += "import "+imports.get(i)+";\n";
		}
		
		if (imports.size() > 0)
			classCode += "\n";

		for (String annotation:annotations)
			classCode += annotation+"\n"; 
		
		classCode += "public class "+className+" ";
		
		if (superClass != null)
			classCode += "extends "+superClass+" ";
		
		boolean first = true;
		
		if (interfaces.size() > 0)
		{
			classCode += "implements ";
			
			for (int i=0;i<interfaces.size();i++)
			{
				if (first)
					first = false;
				else
					classCode += ",";
				
				classCode += interfaces.get(i).toString();
			}
		}
		
		classCode += "\n{\n";
		
		for (int i=0;i<fields.size();i++)
		{
			Field field = (Field)fields.get(i);
			classCode += field.generate();
		}
		
		if (fields.size() > 0)
			classCode += "\n";
		
		for (int i=0;i<methods.size();i++)
		{
			CodeGenerator method = (CodeGenerator)methods.get(i);
			classCode += method.generate();
		}
		
		classCode += "}\n";
			
		return classCode;
	}
	
	public void addProperty(String type,String name)
	{
		addProperty(type,name,null);
	}
	
	public void addProperty(String type,String name,String init)
	{
		for (int i=0;i<fields.size();i++)
		{
			Field field = (Field)fields.get(i);
			
			if (field.getVarName().equals(name))
				return;
		}
		
		addField(new Field(false,"private",type,name,init,1));
		
		Method setter = new Method();
		setter.setMethodName(makeSetterName(name));
		setter.addParams(new ParamDefinition(type,name));
		setter.addStatement(new SingleStatement(2,"this."+name+" = "+name+";"));
		addMethod(setter);
		
		Method getter = new Method();
		getter.setReturnType(type);
		getter.setMethodName(makeGetterName(name));
		getter.addStatement(new SingleStatement(2,"return this."+name+";"));
		addMethod(getter);
	}
	
	public static String makeGetterName(String propertyName)
	{
		char ch = propertyName.charAt(0);
		String base = propertyName.substring(1);
		return "get"+Character.toUpperCase(ch)+base;
	}
	
	public static String makeSetterName(String propertyName)
	{
		char ch = propertyName.charAt(0);
		String base = propertyName.substring(1);
		return "set"+Character.toUpperCase(ch)+base;
	}

	public void addImport(String name)
	{
		imports.add(name);
	}
	
	public void addInterface(String name)
	{
		interfaces.add(name);
	}
	
	public void addMethod(Method method)
	{
		methods.add(method);
	}
	
	public void addField(Field field)
	{
		fields.add(field);
	}
	
	public String getClassName()
	{
		return className;
	}
	public void setClassName(String className)
	{
		this.className = className;
	}
	public String getPackageName()
	{
		return packageName;
	}
	public void setPackageName(String packageName)
	{
		this.packageName = packageName;
	}
	public String getSuperClass()
	{
		return superClass;
	}

	public void setSuperClass(String superClass)
	{
		this.superClass = superClass;
	}
	
	public static String tabs(int num)
	{
		String tabs = "";
		
		for (int i=0;i<num;i++)
			tabs += "\t";
		
		return tabs;
	}
}
